home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
game
/
misc
/
WormWars.lha
/
WormWars
/
Source
/
system.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-10-21
|
115KB
|
3,028 lines
/* $Filename: WormWars/Source/system.c $
* $VER: Worm Wars 7.21a for Amiga $
*
* © Copyright 1993-2002 James R. Jacobs. Freely distributable.
* _
* // Only -=AMIGA=- makes it possible
* //
* _ //
* \\ //
* \X/
#INCLUDES ---------------------------------------------------------------- */
#include "amiga.h"
#include "system.h"
// #include <assert.h>
// #define ASSERT
/* PROTOTYPES (Amiga-only) ----------------------------------------------- */
MODULE void freefx(void);
MODULE void loadthefx(void);
MODULE void loadthemusic(void);
MODULE void parsewb(void);
MODULE void pausetimer(void);
MODULE void unpausetimer(void);
MODULE ABOOL beginfx(void);
MODULE UBYTE ReadJoystick(UWORD joynum);
MODULE ABOOL firebutton(void);
IMPORT void align(STRPTR string, SBYTE size, TEXT filler);
AGLOBAL struct Window *HelpWindowPtr = NULL,
*MainWindowPtr = NULL;
AGLOBAL struct Menu* MenuPtr = NULL;
AGLOBAL struct VisualInfo* VisualInfoPtr = NULL;
AGLOBAL struct timerequest* TimerRqPtr = NULL;
AGLOBAL struct Screen* ScreenPtr = NULL;
AGLOBAL ABOOL icons = TRUE;
/* EXTERNAL VARIABLES ----------------------------------------------------- */
IMPORT struct ExecBase* SysBase;
IMPORT ABOOL anims, modified, randomflag, turbo, thick;
IMPORT SBYTE a, eachworm[4][2][9],
level, levels, players, sourcelevel,
startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
IMPORT SWORD secondsleft, secondsperlevel;
IMPORT ULONG delay, r;
IMPORT UBYTE board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
field[FIELDX + 1][FIELDY + 1];
IMPORT struct HiScoreStruct hiscore[HISCORES + 1];
IMPORT struct WormStruct worm[4];
IMPORT UBYTE missileframes[4][MISSILEFRAMES + 1];
IMPORT TEXT pathname[81],
date[DATELENGTH + 1],
times[TIMELENGTH + 1];
IMPORT struct Image Image;
IMPORT UWORD ImageData[ARRAYSIZE + 1][SQUAREY * DEPTH];
struct Library* TimerBase;
struct Library* ASLBase = NULL;
struct DiskFontBase* DiskFontBase = NULL;
struct GadToolsBase* GadToolsBase = NULL;
struct GfxBase* GfxBase = NULL;
struct Library* IconBase = NULL;
struct IntuitionBase* IntuitionBase = NULL;
struct LowLevelBase* LowLevelBase = NULL;
struct MEDPlayerBase* MEDPlayerBase = NULL;
struct UtilityBase* UtilityBase = NULL;
/* MODULE VARIABLES (used only within system.c) --------------------------- */
MODULE ABOOL eversent[4],
ignore = FALSE,
quiet = FALSE;
MODULE SBYTE AudioClosed = TRUE,
OldPri = 0,
TimerClosed = TRUE;
MODULE UBYTE fxable = UNTRIED,
mode = NULL,
musicable = UNTRIED;
MODULE ULONG fsize,
receipter[4] = {(ULONG) -1, (ULONG) -1, (ULONG) -1, (ULONG) -1};
MODULE UBYTE* fbase = NULL;
MODULE BPTR FilePtr = NULL;
MODULE APTR OldWindowPtr = NULL;
MODULE SBYTE hiframe = -1;
MODULE UBYTE ConfigBuffer[22];
MODULE UWORD DisplayDepth = DEPTH;
MODULE ULONG DisplayID = HIRES_KEY | PAL_MONITOR_ID | LACE,
DisplayWidth = ENTIREXPIXEL,
DisplayHeight = ENTIREYPIXEL;
// MODULE struct QDPlaneInfo QDPI;
// MODULE ABOOL useqdraw = FALSE;
MODULE struct TextAttr WormWars8 =
{ (STRPTR) "WormWars.font", 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
}, Topaz8 =
{ (STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
};
MODULE struct Gadget *CycleGadgetPtr[4] = {NULL, NULL, NULL, NULL},
*GListPtr = NULL,
*PrevGadgetPtr = NULL,
*RandomGadgetPtr = NULL,
*FEGadgetPtr = NULL,
*PlayGadgetPtr = NULL,
*StringGadgetPtr[5] = {NULL, NULL, NULL, NULL, NULL};
MODULE struct MsgPort *AudioPortPtr[4] = {NULL, NULL, NULL, NULL},
*TimerPortPtr = NULL;
MODULE struct timeval *CurrentValPtr = NULL,
*PausedValPtr = NULL,
*StartValPtr = NULL;
MODULE struct CIA* CIAPtr = (struct CIA *) 0xBFE001;
MODULE struct RDArgs* ArgsPtr = NULL;
MODULE struct FileRequester* ASLRqPtr = NULL;
MODULE struct IOAudio* AudioRqPtr[4] = {NULL, NULL, NULL, NULL};
MODULE struct TextFont* FontPtr = NULL;
MODULE struct Process* ProcessPtr = NULL;
MODULE struct MMD0* SongPtr = NULL;
MODULE struct WBArg* WBArg = NULL;
MODULE struct WBStartup* WBMsg = NULL;
#define CENTREXPIXEL (STARTXPIXEL + ((ENDXPIXEL - STARTXPIXEL) / 2))
#define CENTREYPIXEL (STARTYPIXEL + ((ENDYPIXEL - STARTYPIXEL) / 2))
#define RUNDOWNX 234
#define RUNDOWNY 96
#define RUNDOWNY_2ND (SQUAREY * 11)
#define RUNDOWNLENGTH 27
#define RUNDOWNX_2ND (FONTX * 14)
#define RUNDOWNX_3RD (FONTX * 21)
#define RUNDOWNX_4TH (FONTX * 28)
/* FUNCTIONS -------------------------------------------------------------- */
int main(int argc, char** argv)
{
BPTR FileHandle,
OldDir;
SBYTE error = 0,
player,
which;
TEXT saystring[SAYLIMIT + 1];
SWORD oldsecondsleft;
SLONG i,
args[12] = {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
struct ScreenModeRequester* smr;
ABOOL ok;
UWORD Pens[10] =
{ BLACK, /* DETAILPEN text in title bar */
WHITE, /* BLOCKPEN fill title bar */
BLACK, /* TEXTPEN regular text on BACKGROUNDPEN */
LIGHTGREY, /* SHINEPEN bright edge */
DARKGREY, /* SHADOWPEN dark edge */
BLUE, /* FILLPEN filling active window borders
and selected gadgets */
BLACK, /* FILLTEXTPEN text rendered over FILLPEN */
MEDIUMGREY,/* BACKGROUNDPEN background colour */
RED, /* HIGHLIGHTTEXTPEN highlighted text on BACKGROUNDPEN */
(UWORD) ~0 /* and used against BLOCKPEN in ASL save requesters */
};
struct ColorSpec Colours[21] =
{ { 0, 0x0, 0x0, 0x0}, // black
{ 1, 0xA, 0xA, 0xA}, // light grey
{ 2, 0x3, 0x6, 0x3}, // dark green
{ 3, 0x6, 0x6, 0x3}, // dark yellow
{ 4, 0x5, 0x5, 0x5}, // medium grey
{ 5, 0x4, 0x4, 0xA}, // dark blue
{ 6, 0x8, 0x8, 0xF}, // light blue
{ 7, 0x7, 0xB, 0x7}, // light green
{ 8, 0x9, 0x3, 0x3}, // dark red
{ 9, 0x8, 0x4, 0x2}, // brown
{10, 0xF, 0x5, 0x5}, // light red
{11, 0xB, 0xB, 0x6}, // light yellow
{12, 0x2, 0x2, 0x2}, // dark grey
{13, 0xF, 0x9, 0x8}, // orange
{14, 0xF, 0x8, 0xF}, // purple
{15, 0xF, 0xF, 0xF}, // white
{16, 0x0, 0x0, 0x0}, /* pointer: transparent */
{17, 0xE, 0x4, 0x4}, /* pointer: fill */
{18, 0x3, 0x3, 0x3}, /* pointer: shadow */
{19, 0xC, 0xC, 0xC}, /* pointer: shine */
{-1, NULL,NULL,NULL}
};
// Start of program.
// version embedding into executable
if (0) /* that is, never */
{ say(VERSION, ANYTHING);
}
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37L)))
{ Write(Output(), OLDKICKSTART, strlen(OLDKICKSTART));
cleanexit(EXIT_FAILURE);
}
/* From this point onwards, we can be sure we have Kickstart 2.04+... */
for (i = 0; i <= SAMPLES; i++)
{ samp[i].base = NULL;
}
enginesetup();
ProcessPtr = (struct Process *) FindTask(NULL);
if (SysBase->LibNode.lib_Version < 36L)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Need exec.library V36+!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open graphics.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 37L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open GadTools.library V37+!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open ASL.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(UtilityBase = (struct UtilityBase *) OpenLibrary("utility.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open utility.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(IconBase = (struct Library *) OpenLibrary("icon.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open icon.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
LowLevelBase = (struct Library *) OpenLibrary("lowlevel.library", 0L);
ok = FALSE;
if (FileHandle = Open("PROGDIR:WormWars.config", MODE_OLDFILE))
{ if (Read(FileHandle, ConfigBuffer, 22) == 22)
{ ok = TRUE;
for (player = 0; player <= 3; player++)
{ worm[player].control = (UBYTE) ConfigBuffer[player];
}
DisplayID = (ULONG) ( (ConfigBuffer[ 4] * 16777216)
+ (ConfigBuffer[ 5] * 65536)
+ (ConfigBuffer[ 6] * 256)
+ ConfigBuffer[ 7] );
DisplayWidth = (ULONG) ( (ConfigBuffer[ 8] * 16777216)
+ (ConfigBuffer[ 9] * 65536)
+ (ConfigBuffer[10] * 256)
+ ConfigBuffer[11] );
DisplayHeight = (ULONG) ( (ConfigBuffer[12] * 16777216)
+ (ConfigBuffer[13] * 65536)
+ (ConfigBuffer[14] * 256)
+ ConfigBuffer[15] );
DisplayDepth = (UWORD) ( (ConfigBuffer[16] * 256)
+ ConfigBuffer[17] );
randomflag = (ABOOL) ConfigBuffer[18];
icons = (ABOOL) ConfigBuffer[19];
thick = (ABOOL) ConfigBuffer[20];
anims = (ABOOL) ConfigBuffer[21];
}
Close(FileHandle);
// FileHandle = NULL;
}
/* argument parsing */
if (argc) /* started from CLI */
{ if (!(ArgsPtr = ReadArgs
( "-N=NOPRELOAD/S,-A=NOANIMS/S,-I=NOICONS/S,-P=PRI/K/N,"
"-S=SHUFFLE/S,-Q=QUIET/S,GREEN/K,RED/K,BLUE/K,YELLOW/K,"
"-T=THICKTAILS,FILE",
(LONG *) args,
NULL
)))
{ Printf
( "Usage: %s [-n=NOPRELOAD] [-a=NOANIMS] [-i=NOICONS] "
"[-p=PRI <priority>] [-s=SHUFFLE] [-q=QUIET] "
"[GREEN=KYBD|JOY|GAMEPAD|AMIGA|NONE] "
"[RED=KYBD|JOY|GAMEPAD|AMIGA|NONE] [BLUE=JOY|GAMEPAD|AMIGA|NONE] "
"[YELLOW=JOY|GAMEPAD|AMIGA|NONE] [[FILE=]<fieldset>]\n",
argv[0]
);
cleanexit(EXIT_FAILURE);
}
if (args[0])
{ fxable = musicable = DEFER;
}
if (args[1])
{ anims = FALSE;
}
if (args[2])
{ icons = FALSE;
}
if (args[3])
{ if (args[3] < -128 || args[3] > 5)
{ Printf("%s: Priority range is -128 to +5\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
OldPri = SetTaskPri((struct Task *) ProcessPtr, args[3]);
}
if (args[4])
{ randomflag = TRUE;
}
if (args[5])
{ quiet = TRUE;
}
if (args[6])
{ if (!stricmp(args[6], "KYBD"))
{ worm[0].control = KEYBOARD;
} elif (!stricmp(args[6], "JOY"))
{ worm[0].control = JOYSTICK;
} elif (!stricmp(args[6], "GAMEPAD"))
{ if (!LowLevelBase)
{ Printf("%s: Can't open lowlevel.library!\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
worm[0].control = GAMEPAD;
} elif (!stricmp(args[6], "AMIGA"))
{ worm[0].control = AMIGA;
} elif (!stricmp(args[6], "NONE"))
{ worm[0].control = NONE;
} else
{ Printf("%s: Green worm control must be KYBD, JOY, GAMEPAD, AMIGA or NONE\n", argv[0]);
cleanexit(EXIT_FAILURE);
} }
if (args[7])
{ if (!stricmp(args[7], "KYBD"))
{ worm[1].control = KEYBOARD;
} elif (!stricmp(args[7], "JOY"))
{ worm[1].control = JOYSTICK;
} elif (!stricmp(args[7], "GAMEPAD"))
{ if (!LowLevelBase)
{ Printf("%s: Can't open lowlevel.library!\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
worm[1].control = GAMEPAD;
} elif (!stricmp(args[7], "AMIGA"))
{ worm[1].control = AMIGA;
} elif (!stricmp(args[7], "NONE"))
{ worm[1].control = NONE;
} else
{ Printf("%s: Red worm control must be KYBD, JOY, GAMEPAD, AMIGA or NONE\n", argv[0]);
cleanexit(EXIT_FAILURE);
} }
if (args[8])
{ if (!stricmp(args[8], "JOY"))
{ worm[2].control = JOYSTICK;
} elif (!stricmp(args[8], "GAMEPAD"))
{ if (!LowLevelBase)
{ Printf("%s: Can't open lowlevel.library!\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
worm[2].control = GAMEPAD;
} elif (!stricmp(args[8], "AMIGA"))
{ worm[2].control = AMIGA;
} elif (!stricmp(args[8], "NONE"))
{ worm[2].control = NONE;
} else
{ Printf("%s: Blue worm control must be JOY, GAMEPAD, AMIGA or NONE\n", argv[0]);
cleanexit(EXIT_FAILURE);
} }
if (args[9])
{ if (!stricmp(args[9], "JOY"))
{ worm[3].control = JOYSTICK;
} elif (!stricmp(args[9], "GAMEPAD"))
{ if (!LowLevelBase)
{ Printf("%s: Can't open lowlevel.library!\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
worm[3].control = GAMEPAD;
} elif (!stricmp(args[9], "AMIGA"))
{ worm[3].control = AMIGA;
} elif (!stricmp(args[9], "NONE"))
{ worm[3].control = NONE;
} else
{ Printf("%s: Yellow worm control must be JOY, GAMEPAD, AMIGA or NONE\n", argv[0]);
cleanexit(EXIT_FAILURE);
} }
if (args[10])
{ thick = TRUE;
}
if (args[11])
{ strcpy(pathname, args[11]);
} }
else /* started from WB */
{ WBMsg = (struct WBStartup *) argv;
WBArg = WBMsg->sm_ArgList; /* head of the arg list */
for (i = 0;
i < WBMsg->sm_NumArgs;
i++, WBArg++)
{ if (WBArg->wa_Lock)
{ /* something that does not support locks */
parsewb();
}
else
{ /* locks supported, change to the proper directory */
OldDir = CurrentDir(WBArg->wa_Lock);
parsewb();
CurrentDir(OldDir);
}
if (i == 1)
{ strcpy(pathname, WBArg->wa_Name);
} } }
if (!(DiskFontBase = (struct DiskFontBase *) OpenLibrary("diskfont.library", 0L)))
error = 1;
if
( (!(StartValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
|| (!(CurrentValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
|| (!(PausedValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer value structure!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(TimerPortPtr = (struct MsgPort *) CreateMsgPort()))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer message port!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(TimerRqPtr = (struct timerequest *) CreateIORequest(TimerPortPtr, sizeof(struct timerequest))))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create timer I/O request!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (TimerClosed = OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *) TimerRqPtr, 0))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open timer.device!\0", 24);
cleanexit(EXIT_FAILURE);
}
TimerBase = (struct Library *) TimerRqPtr->tr_node.io_Device;
if (!ok && ASLBase->lib_Version >= 38L)
{ if (!(smr = (struct ScreenModeRequester *) AllocAslRequestTags
( ASL_ScreenModeRequest,
ASLSM_TitleText, "Worm Wars: Screen Mode Requester",
ASLSM_InitialDisplayID, HIRES_KEY | PAL_MONITOR_ID | LACE,
ASLSM_InitialDisplayWidth, ENTIREXPIXEL,
ASLSM_InitialDisplayHeight, ENTIREYPIXEL,
ASLSM_InitialDisplayDepth, DEPTH,
ASLSM_DoWidth, TRUE,
ASLSM_DoHeight, TRUE,
ASLSM_DoDepth, TRUE,
ASLSM_MinWidth, ENTIREXPIXEL,
ASLSM_MinHeight, ENTIREYPIXEL,
ASLSM_MinDepth, DEPTH,
TAG_DONE
)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL screen mode request!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (AslRequest(smr, 0L))
{ DisplayID = smr->sm_DisplayID;
DisplayWidth = smr->sm_DisplayWidth;
DisplayHeight = smr->sm_DisplayHeight;
DisplayDepth = smr->sm_DisplayDepth;
}
FreeAslRequest(smr);
}
/* PREPARE DISPLAY -----------------------------------------------
font and screen */
if ((!error) && (FontPtr = (struct TextFont *) OpenDiskFont(&WormWars8)))
{ /* loaded WormWars.font */
ScreenPtr = (struct Screen *) OpenScreenTags
( NULL,
SA_Width, DisplayWidth,
SA_Height, DisplayHeight,
SA_Depth, DisplayDepth,
SA_DisplayID, DisplayID,
SA_Title, TITLEBAR,
SA_Colors, Colours,
SA_Font, &WormWars8,
SA_Pens, Pens,
SA_PubName, "WORMWARS",
TAG_DONE
);
if (!ScreenPtr)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen!\0", 24);
cleanexit(EXIT_FAILURE);
} }
else
{ if (!error)
; // error = 2;
ScreenPtr = (struct Screen *) OpenScreenTags
( NULL,
SA_Width, DisplayWidth,
SA_Height, DisplayHeight,
SA_Depth, DisplayDepth,
SA_DisplayID, DisplayID,
SA_Title, TITLEBAR,
SA_Colors, Colours,
SA_Font, &Topaz8,
SA_Pens, Pens,
SA_PubName, "WORMWARS",
TAG_DONE
);
if (!ScreenPtr)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen nor font!\0", 24);
cleanexit(EXIT_FAILURE);
} }
PubScreenStatus(ScreenPtr, NULL); // take the screen public
/* For some reason, we lose 4 memory chunks around this point: 2 chunks
each of 292 bytes and 10 bytes. It is related to OpenScreenTagList(),
but is not related to the SA_Colors, SA_Font or SA_Pens tags, nor to
the timer.device. Perhaps it is due to the public nature of the screen?
Now that the screen is set up, we initialize the turbo graphics as
follows: */
/* for (i = 0; i < DEPTH; i++)
QDPI.pi_Planes[i] = ScreenPtr->RastPort.BitMap->Planes[i];
QDPI.pi_BPR = ScreenPtr->RastPort.BitMap->BytesPerRow;
QDPI.pi_PlaneSZ = ScreenPtr->RastPort.BitMap->BytesPerRow *
ScreenPtr->RastPort.BitMap->Rows;
*/
// These must be done before the menus are set up
if (anims)
{ NewMenu[INDEX_ANIMATIONS].nm_Flags |= CHECKED;
}
if (icons)
{ NewMenu[INDEX_CREATEICONS].nm_Flags |= CHECKED;
}
if (thick)
{ NewMenu[INDEX_THICKTAILS].nm_Flags |= CHECKED;
}
/* GadTools */
if
( !( CycleGadget.ng_VisualInfo
= StringGadget.ng_VisualInfo
= RandomGadget.ng_VisualInfo
= FEGadget.ng_VisualInfo
= PlayGadget.ng_VisualInfo
= VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)
) )
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't get GadTools visual info!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create menus!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(LayoutMenus(MenuPtr, VisualInfoPtr, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't lay out menus!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools context!\0", 24);
cleanexit(EXIT_FAILURE);
}
for (player = 0; player <= 3; player++)
{ CycleGadget.ng_TopEdge = TSOFFSET + 200 + (player * (FONTX + 8));
CycleGadgetPtr[player] = PrevGadgetPtr = (struct Gadget *) CreateGadget
( CYCLE_KIND,
PrevGadgetPtr,
&CycleGadget,
GTCY_Labels, CycleOptions[player],
GTCY_Active, worm[player].control,
GT_Underscore, '_',
GA_Disabled, TRUE,
TAG_DONE
);
}
RandomGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
( CHECKBOX_KIND,
PrevGadgetPtr,
&RandomGadget,
GTCB_Checked, randomflag,
GT_Underscore, '_',
GA_Disabled, TRUE,
TAG_DONE
);
PlayGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
( BUTTON_KIND,
PrevGadgetPtr,
&PlayGadget,
GA_Disabled, TRUE,
TAG_DONE
);
FEGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
( BUTTON_KIND,
PrevGadgetPtr,
&FEGadget,
GA_Disabled, TRUE,
TAG_DONE
);
/* main window */
if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Top, 11,
WA_Width, SCREENXPIXEL,
WA_Height, SCREENYPIXEL,
WA_IDCMP, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS,
WA_Gadgets, GListPtr,
WA_CustomScreen, ScreenPtr,
WA_Borderless, TRUE,
WA_Activate, TRUE,
WA_SmartRefresh, TRUE,
WA_ReportMouse, TRUE,
WA_RptQueue, 16,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open main window!\0", 24);
cleanexit(EXIT_FAILURE);
}
/* redirection of AmigaDOS system requesters */
OldWindowPtr = ProcessPtr->pr_WindowPtr;
ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, PATTERN, ASL_Window, MainWindowPtr, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL request!\0", 24);
cleanexit(EXIT_FAILURE);
}
/* String gadgets: first the window is opened with the cycle and
checkbox gadgets.
It is necessary not to display the string gadgets yet, so the
gadgets are then created and added to the gadget list. You will note
there is no command given to render them as yet. When the attributes
are modified at highscore time, the applicable gadget is refreshed
then. */
for (which = 0; which <= HISCORES; which++)
{ StringGadget.ng_TopEdge = TSOFFSET + 4 + (which * HISCOREDISTANCE);
StringGadgetPtr[which] = PrevGadgetPtr = (struct Gadget *) CreateGadget(STRING_KIND, PrevGadgetPtr, &StringGadget, GTST_MaxChars, NAMELENGTH, STRINGA_ReplaceMode, TRUE, GA_Disabled, TRUE, TAG_DONE);
}
if (!PrevGadgetPtr)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools gadgets!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (musicable == UNTRIED)
loadthemusic();
if (fxable == UNTRIED)
loadthefx();
if (fxable == SUCCEEDED)
toggle(F);
else if (musicable == SUCCEEDED)
toggle(M);
strcpy(saystring, "Loading ");
strcat(saystring, pathname);
strcat(saystring, "...");
say(saystring, WHITE);
if (loadfields(pathname))
{ if (!quiet)
{ strcpy(saystring, "Can't open ");
strcat(saystring, pathname);
strcat(saystring, "!");
say(saystring, RED);
}
newfields();
if (!quiet)
{ anykey(TRUE);
} }
while (1)
{ titlescreen();
for (i = 0; i <= 3; i++)
{ if (worm[i].control == GAMEPAD)
{ SetJoyPortAttrs(worm[i].port, SJA_Type, SJA_TYPE_GAMECTLR, TAG_DONE);
} }
/* MAIN GAME LOOP ------------------------------------------------- */
while (a == PLAYGAME)
{ r++;
oldsecondsleft = secondsleft;
GetSysTime(CurrentValPtr);
SubTime(CurrentValPtr, StartValPtr);
secondsleft = secondsperlevel - CurrentValPtr->tv_secs;
if (secondsleft != oldsecondsleft)
timeloop();
if (!turbo)
{ TimerRqPtr->tr_node.io_Command = TR_ADDREQUEST;
TimerRqPtr->tr_time.tv_secs = 0;
TimerRqPtr->tr_time.tv_micro = delay;
SendIO((struct IORequest *) TimerRqPtr);
}
gameloop();
// CheckIO() returns FALSE if complete, pointer if incomplete.
if (CheckIO((struct IORequest *) TimerRqPtr)) // CheckIO returns pointer to struct IORequest
draw(CLOCKICON, ICONY, CLOCK);
else draw(CLOCKICON, ICONY, BLACKENED);
WaitIO((struct IORequest *) TimerRqPtr);
}
say("Title Screen", WHITE);
} }
/* SUPPORT FUNCTIONS ----------------------------------------------------- */
/* NAME anykey -- wait for a user press
SYNOPSIS anykey(ABOOL);
FUNCTION Waits for a user response. Optional automatic timeout.
INPUTS timeout - timeout?
RESULTS FALSE if user presses Escape, TRUE otherwise.
FILE system.c */
ABOOL anykey(ABOOL timeout)
{ ABOOL done = FALSE;
SBYTE count = 0;
UWORD code, qual;
ULONG class;
struct IntuiMessage* MsgPtr;
clearkybd();
Forbid();
MainWindowPtr->Flags |= WFLG_RMBTRAP;
Permit();
while (!done && !firebutton())
{ while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch(class)
{
case IDCMP_RAWKEY:
if ((!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
{ done = TRUE;
if (code == M)
toggle(M);
elif (code == F)
toggle(F);
elif (code == ESCAPE)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
{ cleanexit(EXIT_SUCCESS);
} else
{ Forbid();
MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
Permit();
return(FALSE);
} } } }
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
case IDCMP_ACTIVEWINDOW:
ignore = TRUE;
break;
case IDCMP_MOUSEBUTTONS:
if ((code == SELECTDOWN || code == MENUDOWN) && !(qual & IEQUALIFIER_REPEAT))
if (ignore)
ignore = FALSE;
else done = TRUE;
break;
case IDCMP_INTUITICKS:
if (timeout && ++count > PATIENCE)
done = TRUE;
break;
default:
break;
} } }
Forbid();
MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
Permit();
return TRUE;
}
void celebrate(void)
{ ABOOL done = FALSE;
ULONG class;
UWORD code, qual;
struct IntuiMessage* MsgPtr;
UBYTE player;
for (player = 0; player <= 3; player++)
if (worm[player].control != NONE && worm[player].score >= worm[player].hiscore)
worm[player].hiscore = worm[player].score;
waitasec();
clearkybd();
while (!done && !firebutton)
{ while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch (class)
{
case IDCMP_RAWKEY:
if (code == ESCAPE)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
{ cleanexit(EXIT_SUCCESS);
} }
else
{ done = TRUE;
} }
elif (code == RETURN || code == ENTER || code == SPACEBAR)
{ done = TRUE;
} elif (code == M)
{ toggle(M);
} elif (code == F)
{ toggle(F);
}
break;
case IDCMP_MOUSEBUTTONS:
if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
{ if (ignore)
{ ignore = FALSE;
}
else
{ done = TRUE;
} }
break;
case IDCMP_ACTIVEWINDOW:
ignore = TRUE;
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
default:
break;
} }
SetRGB4(&ScreenPtr->ViewPort, 17, rand() % 16, rand() % 16, rand() % 16);
draw(rand() % (FIELDX + 1), rand() % (FIELDY + 1), rand() % LASTOBJECT);
}
SetRGB4(&ScreenPtr->ViewPort, 17, 14, 4, 4);
a = GAMEOVER;
}
void cleanexit(SLONG rc)
{ SBYTE i;
BPTR FileHandle;
// CheckIO() returns NULL if complete, pointer if incomplete?
if (TimerRqPtr && (!CheckIO((struct IORequest *) TimerRqPtr)))
{ AbortIO((struct IORequest *) TimerRqPtr);
WaitIO((struct IORequest *) TimerRqPtr);
}
freefx();
for (i = 0; i <= SAMPLES; i++)
if (samp[i].base)
FreeMem(samp[i].base, samp[i].size);
if (mode == MUSIC) StopPlayer();
if (SongPtr) UnLoadModule(SongPtr);
if (MEDPlayerBase) { FreePlayer();
CloseLibrary((struct Library *) MEDPlayerBase);
}
if (ASLRqPtr) FreeAslRequest(ASLRqPtr);
if (OldWindowPtr) ProcessPtr->pr_WindowPtr = OldWindowPtr;
if (MainWindowPtr) { clearkybd();
ClearMenuStrip(MainWindowPtr);
CloseWindow(MainWindowPtr); }
if (GListPtr) FreeGadgets(GListPtr);
if (MenuPtr) FreeMenus(MenuPtr);
if (VisualInfoPtr) FreeVisualInfo(VisualInfoPtr);
if (ScreenPtr) CloseScreen(ScreenPtr);
if (FontPtr) CloseFont(FontPtr);
if (!TimerClosed) CloseDevice((struct IORequest *) TimerRqPtr);
if (TimerRqPtr) DeleteIORequest(TimerRqPtr);
if (TimerPortPtr) DeleteMsgPort(TimerPortPtr);
if (PausedValPtr) FreeMem(PausedValPtr, sizeof(struct timeval));
if (CurrentValPtr) FreeMem(CurrentValPtr, sizeof(struct timeval));
if (StartValPtr) FreeMem(StartValPtr, sizeof(struct timeval));
if (DiskFontBase) CloseLibrary((struct Library *) DiskFontBase);
if (LowLevelBase)
{ for (i = 0; i <= 3; i++)
{ SetJoyPortAttrs(worm[i].port, SJA_Reinitialize, TRUE, TAG_DONE);
}
CloseLibrary((struct Library *) LowLevelBase);
}
if (UtilityBase) CloseLibrary((struct Library *) UtilityBase);
if (ASLBase) CloseLibrary((struct Library *) ASLBase);
if (GadToolsBase) CloseLibrary((struct Library *) GadToolsBase);
if (GfxBase) CloseLibrary((struct Library *) GfxBase);
if (IconBase) CloseLibrary((struct Library *) IconBase);
if (IntuitionBase) { OpenWorkBench();
CloseLibrary((struct Library *) IntuitionBase); }
SetTaskPri((struct Task *) ProcessPtr, OldPri);
if (ArgsPtr) FreeArgs(ArgsPtr);
for (i = 0; i <= 3; i++)
{ ConfigBuffer[i] = (SBYTE) worm[i].control;
}
ConfigBuffer[ 4] = (UBYTE) (DisplayID / 16777216);
ConfigBuffer[ 5] = (UBYTE) ((DisplayID % 16777216) / 65536);
ConfigBuffer[ 6] = (UBYTE) (((DisplayID % 16777216) % 65536) / 256);
ConfigBuffer[ 7] = (UBYTE) (((DisplayID % 16777216) % 65536) % 256);
ConfigBuffer[ 8] = (UBYTE) (DisplayWidth / 16777216);
ConfigBuffer[ 9] = (UBYTE) ((DisplayWidth % 16777216) / 65536);
ConfigBuffer[10] = (UBYTE) (((DisplayWidth % 16777216) % 65536) / 256);
ConfigBuffer[11] = (UBYTE) (((DisplayWidth % 16777216) % 65536) % 256);
ConfigBuffer[12] = (UBYTE) (DisplayHeight / 16777216);
ConfigBuffer[13] = (UBYTE) ((DisplayHeight % 16777216) / 65536);
ConfigBuffer[14] = (UBYTE) (((DisplayHeight % 16777216) % 65536) / 256);
ConfigBuffer[15] = (UBYTE) (((DisplayHeight % 16777216) % 65536) % 256);
ConfigBuffer[16] = (UBYTE) (DisplayDepth / 65536);
ConfigBuffer[17] = (UBYTE) (DisplayDepth % 65536);
ConfigBuffer[18] = (UBYTE) randomflag;
ConfigBuffer[19] = (UBYTE) icons;
ConfigBuffer[20] = (UBYTE) thick;
ConfigBuffer[21] = (UBYTE) anims;
if (FileHandle = Open("PROGDIR:WormWars.config", MODE_NEWFILE))
{ Write(FileHandle, ConfigBuffer, 22);
Close(FileHandle);
// FileHandle = NULL;
}
exit(rc); /* End of program. */
}
void clearkybd(void)
{ struct IntuiMessage* MsgPtr;
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
GT_ReplyIMsg(MsgPtr);
}
void effect(SBYTE index)
{ AUTO SBYTE i;
AUTO SBYTE ok = -1;
AUTO ULONG oldestreceipt = (ULONG) -1L;
PERSIST ULONG nextreceipt = 1L;
/* oldestreceipt = temporary variable for ascertaining oldest
sound still playing.
nextreceipt = next unused receipt number (monotonically incrementing). */
if (mode == FX)
{ for (i = 0; i <= 3; i++)
{ /* decide on a channel */
if (ok == -1)
{ if (!eversent[i])
ok = i;
// CheckIO() returns NULL if complete, pointer if incomplete.
elif (CheckIO((struct IORequest *) AudioRqPtr[i]))
{ WaitIO((struct IORequest *) AudioRqPtr[i]);
ok = i;
} } }
if (ok == -1)
{ for (i = 0; i <= 3; i++)
if (receipter[i] < oldestreceipt)
{ ok = i;
oldestreceipt = receipter[i];
}
AbortIO((struct IORequest *) AudioRqPtr[ok]);
WaitIO((struct IORequest *) AudioRqPtr[ok]);
}
eversent[ok] = TRUE;
AudioRqPtr[ok]->ioa_Cycles = 1;
AudioRqPtr[ok]->ioa_Request.io_Command = CMD_WRITE;
AudioRqPtr[ok]->ioa_Request.io_Flags = ADIOF_PERVOL;
AudioRqPtr[ok]->ioa_Request.io_Unit = (struct Unit *) (1 << ok);
AudioRqPtr[ok]->ioa_Volume = samp[index].volume;
AudioRqPtr[ok]->ioa_Period = (UWORD) samp[index].speed;
AudioRqPtr[ok]->ioa_Request.io_Message.mn_ReplyPort
= AudioPortPtr[ok];
AudioRqPtr[ok]->ioa_Data = (UBYTE *) samp[index].base;
AudioRqPtr[ok]->ioa_Length = samp[index].length[samp[index].bank];
BeginIO(AudioRqPtr[ok]);
receipter[ok] = nextreceipt;
} }
AGLOBAL void help(UBYTE type)
{ TEXT title[10], tempstring[12];
SWORD x, y;
UBYTE i;
effect(FXHELP);
if (type == ORB)
{ strcpy(title, "Creatures");
x = 232;
y = 28 + ((CREATUREHELPS + 1) * SQUAREY);
} else
{ strcpy(title, "Objects");
x = 640;
y = 32 + ((LASTOBJECT / 2) * SQUAREY);
}
if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (SCREENXPIXEL / 2) - (x / 2),
WA_Top, (SCREENYPIXEL / 2) - (y / 2),
WA_Width, x,
WA_Height, y,
WA_IDCMP, IDCMP_CLOSEWINDOW |
IDCMP_RAWKEY |
IDCMP_MOUSEBUTTONS |
IDCMP_INTUITICKS,
WA_Title, title,
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
TAG_DONE)))
{ say("Can't open help window!", RED);
anykey(TRUE);
} else
{ SetAPen(HelpWindowPtr->RPort, WHITE);
if (type == ORB)
{ Move(HelpWindowPtr->RPort, 26 + (14 * FONTX), 20);
Text(HelpWindowPtr->RPort, "Pts Dmg", 9);
Move(HelpWindowPtr->RPort, 26, 22);
Draw(HelpWindowPtr->RPort, 212, 22);
for (i = 0; i <= CREATUREHELPS; i++)
{ Image.ImageData = ImageData[creaturehelp[i].image];
DrawImage
( HelpWindowPtr->RPort,
&Image,
10,
22 + (i * SQUAREY)
);
Move(HelpWindowPtr->RPort, 26 , 31 + (i * SQUAREY));
Text(HelpWindowPtr->RPort, creaturehelp[i].desc, strlen(creaturehelp[i].desc));
stcl_d(tempstring, creaturehelp[i].score);
align(tempstring, 3, ' ');
Move(HelpWindowPtr->RPort, 26 + (14 * 8), 31 + (i * SQUAREY));
Text(HelpWindowPtr->RPort, tempstring, 3);
stcl_d(tempstring, creaturehelp[i].pain);
Move(HelpWindowPtr->RPort, 26 + (21 * 8), 31 + (i * SQUAREY));
Text(HelpWindowPtr->RPort, tempstring, strlen(tempstring));
} }
else
{ // assert(type == AFFIXER);
for (i = 0; i <= LASTOBJECT; i++)
{ Image.ImageData = ImageData[i];
if (i <= LASTOBJECT / 2)
{ Move(HelpWindowPtr->RPort, 26, 24 + (i * SQUAREY));
DrawImage
( HelpWindowPtr->RPort,
&Image,
10,
15 + (i * SQUAREY)
);
} else
{ Move(HelpWindowPtr->RPort, 354, 24 - SQUAREY + ((i - (LASTOBJECT / 2)) * SQUAREY));
DrawImage
( HelpWindowPtr->RPort,
&Image,
338,
15 - SQUAREY + ((i - (LASTOBJECT / 2)) * SQUAREY)
);
}
Text(HelpWindowPtr->RPort, objectdesc[i], strlen(objectdesc[i]));
} }
helploop(type);
} }
AGLOBAL void helpabout(void)
{ SBYTE line;
SLONG projectval;
TEXT projectstring[7], ks[5] = " ", wb[5] = " ";
ULONG ksval = SysBase->LibNode.lib_Version,
wbval = IconBase->lib_Version;
effect(FXHELP);
if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (SCREENXPIXEL / 2) - (ABOUTXPIXEL / 2),
WA_Top, (SCREENYPIXEL / 2) - (ABOUTYPIXEL / 2),
WA_Width, ABOUTXPIXEL,
WA_Height, ABOUTYPIXEL,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, "About Worm Wars",
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
TAG_DONE)))
{ say("Can't open About... window!", RED);
anykey(TRUE);
} else
{ /* calculate project size */
projectval =
10 // header
+ ((HISCORES + 1) * HISCORESIZE) // high scores
+ ((levels + 1) * (8 + (LEVELSIZE))) // level data
+ strlen(VERSION); // version string
switch(ksval)
{
case 37:
strcpy(ks, "2.04");
break;
case 38:
strcpy(ks, "2.1 ");
break;
case 39:
strcpy(ks, "3.0 ");
break;
case 40:
case 41:
case 42:
case 43:
strcpy(ks, "3.1 ");
break;
case 44:
strcpy(ks, "3.5 ");
break;
case 45:
strcpy(ks, "3.9 ");
break;
default:
strcpy(ks, "4.0+");
break;
}
switch(wbval)
{
case 37:
strcpy(wb, "2.04");
break;
case 38:
strcpy(wb, "2.1 ");
break;
case 39:
strcpy(wb, "3.0 ");
break;
case 40:
case 41:
case 42:
case 43:
strcpy(wb, "3.1 ");
break;
case 44:
strcpy(wb, "3.5 ");
break;
case 45:
strcpy(wb, "3.9 ");
break;
default:
strcpy(wb, "4.0+");
break;
}
SetAPen(HelpWindowPtr->RPort, worm[rand() % 4].colour);
RectFill(HelpWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 11, ABOUTYPIXEL - 6);
SetAPen(HelpWindowPtr->RPort, ABOUTSHADOW);
Move(HelpWindowPtr->RPort, 7, ABOUTYPIXEL - 5);
Draw(HelpWindowPtr->RPort, 7, 12);
Draw(HelpWindowPtr->RPort, ABOUTXPIXEL - 10, 12);
SetAPen(HelpWindowPtr->RPort, ABOUTSHINE);
Draw(HelpWindowPtr->RPort, ABOUTXPIXEL - 10, ABOUTYPIXEL - 5);
Draw(HelpWindowPtr->RPort, 8, ABOUTYPIXEL - 5);
SetAPen(HelpWindowPtr->RPort, BLACK);
SetDrMd(HelpWindowPtr->RPort, JAM1);
for (line = 0; line <= ABOUTLINES; line++)
{ Move(HelpWindowPtr->RPort, about[line].x, about[line].y);
Text(HelpWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
}
stcl_d(projectstring, projectval);
align(projectstring, 6, ' ');
Move(HelpWindowPtr->RPort, PROJECTX, PROJECTY);
Text(HelpWindowPtr->RPort, projectstring, 6);
Move(HelpWindowPtr->RPort, KICKSTARTX, KICKSTARTY);
Text(HelpWindowPtr->RPort, ks, 4);
Move(HelpWindowPtr->RPort, WORKBENCHX, WORKBENCHY);
Text(HelpWindowPtr->RPort, wb, 4);
DrawBevelBox(HelpWindowPtr->RPort, 16, 20, 44 + 4, 38 + 4, GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_END);
DrawImage(HelpWindowPtr->RPort, &About, 16 + 2, 20 + 2);
helploop(NOSQUARE);
} }
AGLOBAL void helploop(UBYTE type)
{ ABOOL done = FALSE;
UBYTE objx, objy;
UWORD code, qual;
SWORD mousex, mousey;
SBYTE birdframe = -1, birddir = 1;
ULONG class;
struct IntuiMessage* MsgPtr;
while(!done)
{ Wait(1L << HelpWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GetMsg(HelpWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
mousex = MsgPtr->MouseX;
mousey = MsgPtr->MouseY;
ReplyMsg((struct Message *) MsgPtr);
switch(class)
{
case IDCMP_INTUITICKS:
if (type == ORB && anims)
{ birdframe += birddir;
Image.ImageData = ImageData[BIRD + birdframe];
DrawImage
( HelpWindowPtr->RPort,
&Image,
10,
22
);
if (birdframe == 0)
{ birddir = 1;
} elif (birdframe == 4)
{ birddir = -1;
} }
break;
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
case IDCMP_RAWKEY:
if (code == SPACEBAR || code == RETURN || code == ENTER || code == HELP)
done = TRUE;
elif (code == ESCAPE)
{ if (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
{ if (verify())
{ CloseWindow(HelpWindowPtr);
cleanexit(EXIT_SUCCESS);
} }
else done = TRUE;
}
break;
case IDCMP_MOUSEBUTTONS:
if (a == FIELDEDIT && type == AFFIXER)
{ objx = (mousex - 10) / 328; // which column
objy = (mousey - 13) / 10; // which row
if ((objx == 0 || objx == 1) && (objy >= 0 && objy <= LASTOBJECT / 2))
{ if (objx)
setbrush(objy + 1 + (LASTOBJECT / 2));
else setbrush(objy);
done = TRUE;
} }
break;
default:
break;
} } }
CloseWindow(HelpWindowPtr);
HelpWindowPtr = NULL;
clearkybd();
}
AGLOBAL void filedelete(void)
{ TEXT newpathname[255], temp1[81];
if (AslRequestTags(ASLRqPtr, ASL_Hail, "Delete Fieldset", ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
if (DeleteFile(newpathname))
{ strcpy(temp1, "Deleted ");
strcat(temp1, newpathname);
strcat(temp1, ".");
} else
{ strcpy(temp1, "Couldn't delete ");
strcat(temp1, newpathname);
strcat(temp1, "!");
}
say(temp1, WHITE);
} }
AGLOBAL void fileopen(ABOOL revert)
{ TEXT temp1[81] = {"Opened "}, temp2[3], newpathname[255];
strcpy(newpathname, pathname);
if (revert || (AslRequestTags(ASLRqPtr, ASL_Hail, "Open Fieldset", ASL_FuncFlags, FILF_PATGAD, TAG_DONE) && *(ASLRqPtr->rf_File)))
{ if (!revert)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
}
if (!loadfields(newpathname))
{ strcpy(pathname, newpathname);
strcat(temp1, pathname);
strcat(temp1, " (");
stci_d(temp2, levels);
strcat(temp1, temp2);
strcat(temp1, " levels).");
say(temp1, WHITE);
if (a == FIELDEDIT)
turborender();
else hiscores();
} else
{ strcpy(temp1, "Couldn't open ");
strcat(temp1, newpathname);
strcat(temp1, "!");
say(temp1, WHITE);
} }
if (a == GAMEOVER)
anykey(TRUE);
}
AGLOBAL void filesaveas(ABOOL flag)
{ ABOOL cont = TRUE;
TEXT newpathname[255], temp1[SAYLIMIT + 1], temp2[3];
struct DiskObject* InfoHandle;
/* flag is TRUE for 'save as...', FALSE for 'save'. */
strcpy(newpathname, pathname);
if (flag)
if (AslRequestTags(ASLRqPtr, ASL_Hail, "Save Fieldset", ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
} else cont = FALSE;
if (cont)
{ matchteleports();
strcpy(temp1, "Saving ");
strcat(temp1, newpathname);
strcat(temp1, "...");
say(temp1, WHITE);
if (savefields(newpathname))
{ strcpy(pathname, newpathname);
if (icons)
{ InfoHandle = GetDiskObjectNew(DEFAULTSET);
InfoHandle->do_CurrentX = NO_ICON_POSITION;
InfoHandle->do_CurrentY = NO_ICON_POSITION;
if (!PutDiskObject(pathname, InfoHandle))
{ say("Couldn't write .info file!", RED);
anykey(TRUE);
} }
strcpy(temp1, "Saved ");
strcat(temp1, pathname);
strcat(temp1, " (");
stci_d(temp2, levels);
strcat(temp1, temp2);
strcat(temp1, " levels).");
} else
{ strcpy(temp1, "Couldn't save ");
strcat(temp1, newpathname);
strcat(temp1, "!");
}
say(temp1, WHITE);
if (a == GAMEOVER)
anykey(TRUE);
} }
MODULE void freefx(void)
{ SBYTE i;
stopfx();
if (!AudioClosed)
{ CloseDevice((struct IORequest *) AudioRqPtr[0]);
AudioClosed = TRUE;
}
for (i = 0; i <= 3; i++)
{ if (AudioRqPtr[i])
{ DeleteIORequest(AudioRqPtr[i]);
AudioRqPtr[i] = NULL;
}
if (AudioPortPtr[i])
{ // if we ReplyMsg() first, that causes crashes
DeleteMsgPort(AudioPortPtr[i]);
AudioPortPtr[i] = NULL;
} }
if (fbase)
{ FreeMem(fbase, fsize);
fbase = NULL;
}
if (FilePtr)
{ Close(FilePtr);
FilePtr = NULL;
} }
void gameinput(void)
{ ABOOL allowed = TRUE,
done;
UWORD code, qual;
ULONG class;
struct IntuiMessage* MsgPtr;
SBYTE keyplayer, i;
UBYTE which;
for (which = 0; which <= NUMKEYS; which++)
key[which].down = FALSE;
/* keyboard */
while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
{ if (code < KEYUP)
{ switch(code)
{
case M:
toggle(M);
break;
case F:
toggle(F);
break;
case KEY_T:
// check whether any human worms are playing
for (i = 0; i <= 3; i++)
{ if
( worm[i].control != AMIGA
&& worm[i].control != NONE
&& worm[i].lives
)
{ allowed = FALSE;
break;
} }
if (allowed)
{ if (turbo)
{ turbo = FALSE;
} else
{ turbo = TRUE;
draw(CLOCKICON, ICONY, CLOCK);
} }
break;
case P:
clearkybd();
say("Paused...press P to unpause", WHITE);
pausetimer();
done = FALSE;
while (!done)
{ Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
{ if (code == ESCAPE)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
cleanexit(EXIT_SUCCESS);
} else
{ a = GAMEOVER;
done = TRUE;
worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
} }
elif (code == M)
toggle(M);
elif (code == F)
toggle(F);
elif (code == P)
{ say("Unpaused", WHITE);
done = TRUE;
} } } }
unpausetimer();
break;
case ESCAPE:
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
cleanexit(EXIT_SUCCESS);
} else
{ a = GAMEOVER;
worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
}
break;
default:
for (which = 0; which <= NUMKEYS; which++)
if (code == key[which].scancode)
key[which].down = TRUE;
break;
} } }
elif (class == IDCMP_CLOSEWINDOW)
cleanexit(EXIT_SUCCESS);
elif (class == IDCMP_REFRESHWINDOW)
{ GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
} }
for (which = 0; which <= NUMKEYS; which++)
{ if (key[which].down)
{ if (key[which].special == ONEHUMAN)
{ if
( (worm[0].control == KEYBOARD && worm[1].control != KEYBOARD)
)
wormqueue(0, key[which].deltax, key[which].deltay);
elif
( (worm[1].control == KEYBOARD && worm[0].control != KEYBOARD)
)
wormqueue(1, key[which].deltax, key[which].deltay);
} elif (key[which].special == MOVE || key[which].special == AMMO)
{ if (worm[key[which].player].control == KEYBOARD)
keyplayer = key[which].player;
elif
( key[which].player == 1
&& (worm[0].control == KEYBOARD && worm[1].control != KEYBOARD)
)
keyplayer = 0;
elif
( key[which].player == 0
&& (worm[1].control == KEYBOARD && worm[0].control != KEYBOARD)
)
keyplayer = 1;
else keyplayer = -1;
if (keyplayer != -1)
{ wormqueue(keyplayer, key[which].deltax, key[which].deltay);
} }
elif (worm[1].lives) /* assumes key[which].special == TRAINER */
train(key[which].scancode);
} }
}
void hiscores(void)
{ SBYTE which;
TEXT tempstring[NAMELENGTH + 1];
/* render hiscores
#################################################### # = shadow
# # # # # # % % = shine
# # # # # # %
# # # # # # %
# # # # # # %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
hiframe = 0;
SetDrMd(MainWindowPtr->RPort, JAM1);
for (which = 0; which <= HISCORES; which++)
{ if (hiscore[which].player == -1)
SetAPen(MainWindowPtr->RPort, LIGHTGREY);
else SetAPen(MainWindowPtr->RPort, worm[hiscore[which].player].colour);
RectFill(MainWindowPtr->RPort, 104, TSOFFSET + 4 + (which * HISCOREDISTANCE), 536, TSOFFSET + 13 + (which * HISCOREDISTANCE));
if (hiscore[which].player == 0)
SetAPen(MainWindowPtr->RPort, DARKGREEN);
elif (hiscore[which].player == 1)
SetAPen(MainWindowPtr->RPort, DARKRED);
elif (hiscore[which].player == 2)
SetAPen(MainWindowPtr->RPort, DARKBLUE);
elif (hiscore[which].player == 3)
SetAPen(MainWindowPtr->RPort, DARKYELLOW);
else SetAPen(MainWindowPtr->RPort, DARKGREY);
Move(MainWindowPtr->RPort, 103, TSOFFSET + 14 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 103, TSOFFSET + 3 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 537, TSOFFSET + 3 + (which * HISCOREDISTANCE));
if (hiscore[which].player != -1)
{ /* divider bars */
Move(MainWindowPtr->RPort, 182 - 55, TSOFFSET + 3 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 182 - 55, TSOFFSET + 13 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, 254 - 55, TSOFFSET + 3 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 254 - 55, TSOFFSET + 13 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, 290 - 55, TSOFFSET + 3 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 290 - 55, TSOFFSET + 13 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, 416, TSOFFSET + 3 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 416, TSOFFSET + 13 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, 464, TSOFFSET + 3 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 464, TSOFFSET + 13 + (which * HISCOREDISTANCE));
}
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, 159 - 55, TSOFFSET + 14 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 482 + 55, TSOFFSET + 14 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, 482 + 55, TSOFFSET + 4 + (which * HISCOREDISTANCE));
SetAPen(MainWindowPtr->RPort, BLACK);
if (hiscore[which].player != -1)
{ stci_d(tempstring, which + 1);
tempstring[1] = '.';
Move(MainWindowPtr->RPort, 161 - 55, TSOFFSET + 11 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, tempstring, 2);
stci_d(tempstring, hiscore[which].score);
align(tempstring, 7, ' ');
Move(MainWindowPtr->RPort, 193 - 55, TSOFFSET + 11 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, tempstring, 7);
if (hiscore[which].level == -1)
{ strcpy(tempstring, "All");
} else
{ stci_d(tempstring, hiscore[which].level);
align(tempstring, 3, ' ');
}
Move(MainWindowPtr->RPort, 206, TSOFFSET + 11 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, tempstring, 3);
Move(MainWindowPtr->RPort, 241, TSOFFSET + 11 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, hiscore[which].name, strlen(hiscore[which].name));
Move(MainWindowPtr->RPort, 418, TSOFFSET + 11 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, hiscore[which].time, strlen(hiscore[which].time));
Move(MainWindowPtr->RPort, 466, TSOFFSET + 11 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, hiscore[which].date, strlen(hiscore[which].date));
Image.ImageData = ImageData[missileframes[hiscore[which].player][0]];
DrawImage(MainWindowPtr->RPort, &Image, 540, TSOFFSET + 3 + (which * HISCOREDISTANCE));
} }
SetDrMd(MainWindowPtr->RPort, JAM2);
}
void hiscorenames(void)
{ ULONG class;
ABOOL done;
SBYTE which;
struct IntuiMessage* MsgPtr;
for (which = 0; which <= HISCORES; which++)
{ if (hiscore[which].fresh)
{ GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, FALSE, GTST_String, worm[hiscore[which].player].name, TAG_DONE);
ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
done = FALSE;
while (!done)
{ while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
GT_ReplyIMsg(MsgPtr);
if (class == IDCMP_GADGETUP)
{ done = TRUE;
} elif (class == IDCMP_MOUSEBUTTONS)
{ ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
} elif (class == IDCMP_REFRESHWINDOW)
{ GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
} } }
GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
effect(FXAPPLAUSE);
strcpy(hiscore[which].name, ((struct StringInfo *) (StringGadgetPtr[which]->SpecialInfo))->Buffer);
if (hiscore[which].name[0] >= 'a' && hiscore[which].name[0] <= 'z')
{ hiscore[which].name[0] -= 32;
}
strcpy(worm[hiscore[which].player].name, hiscore[which].name);
hiscore[which].fresh = FALSE;
hiscores();
} } }
MODULE ABOOL beginfx(void)
{ SBYTE i;
PERSIST UBYTE chan[] = {15};
for (i = 0; i <= 3; i++)
{ eversent[i] = FALSE;
if (!(AudioPortPtr[i] = (struct MsgPort *) CreateMsgPort()))
{ freefx();
draw(MUSICICON, ICONY, BLACKENED);
mode = FALSE;
say("No port for effects!", RED);
anykey(TRUE);
return FALSE;
} else if (!(AudioRqPtr[i] = (struct IOAudio *) CreateIORequest(AudioPortPtr[i], sizeof(struct IOAudio))))
{ freefx();
draw(MUSICICON, ICONY, BLACKENED);
mode = FALSE;
say("No I/O memory for effects!", RED);
anykey(TRUE);
return FALSE;
} }
AudioRqPtr[0]->ioa_Request.io_Message.mn_ReplyPort = AudioPortPtr[0];
AudioRqPtr[0]->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
AudioRqPtr[0]->ioa_AllocKey = 0;
AudioRqPtr[0]->ioa_Data = chan;
AudioRqPtr[0]->ioa_Length = 1;
if (AudioClosed = OpenDevice(AUDIONAME, 0L, (struct IORequest *) AudioRqPtr[0], 0L))
{ freefx();
draw(MUSICICON, ICONY, BLACKENED);
mode = FALSE;
say("Can't allocate all channels for effects!", RED);
anykey(TRUE);
return FALSE;
} else
{ for (i = 1; i <= 3; i++)
CopyMem(AudioRqPtr[0], AudioRqPtr[i], sizeof(struct IOAudio));
return TRUE;
} }
void resettime(void)
{ GetSysTime(StartValPtr);
srand((UWORD) StartValPtr->tv_micro);
}
void rundown(SBYTE player)
{ ABOOL done = FALSE, flag = FALSE;
TEXT tempstring[6];
SBYTE i, j, x, y;
UBYTE multiply = worm[player].multi * players;
UWORD counter = 0,
code,
qual;
ULONG levelbonus,
numberbonus,
timebonus,
tailbonus,
class;
struct IntuiMessage* MsgPtr;
clearscreen();
DrawBevelBox(MainWindowPtr->RPort, CENTREXPIXEL - 150, CENTREYPIXEL - 40, 308, 59, GT_VisualInfo, VisualInfoPtr, TAG_END);
SetAPen(MainWindowPtr->RPort, BLACK);
RectFill
( MainWindowPtr->RPort,
CENTREXPIXEL - 149,
CENTREYPIXEL - 39,
CENTREXPIXEL + 148,
CENTREYPIXEL + 17
);
SetAPen(MainWindowPtr->RPort, worm[player].colour);
draw(CENTREX - 11, CENTREY - 2, TREASURE);
if (worm[player].numbers == 0)
{ draw(CENTREX - 11, CENTREY - 1, FIRSTPAIN + player);
} else
{ draw(CENTREX - 11, CENTREY - 1, FIRSTLETTER + worm[player].numbers - 1);
}
draw(CENTREX - 11, CENTREY , CLOCK);
draw(CENTREX - 11, CENTREY + 1, FIRSTGLOW + player);
Move(MainWindowPtr->RPort, RUNDOWNX, RUNDOWNY + RUNDOWNY_2ND );
Text(MainWindowPtr->RPort, " Level Bonus: ## x #### =", RUNDOWNLENGTH);
// 012345678901234567890123456
// now the first quantity
stci_d(tempstring, level - 1);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_2ND, RUNDOWNY + RUNDOWNY_2ND );
Text(MainWindowPtr->RPort, tempstring, 4);
// now the second quantity
stci_d(tempstring, BONUS_LEVEL * multiply);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_3RD, RUNDOWNY + RUNDOWNY_2ND );
Text(MainWindowPtr->RPort, tempstring, 4);
Move(MainWindowPtr->RPort, RUNDOWNX, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 1));
Text(MainWindowPtr->RPort, "Number Bonus: ## x #### =", RUNDOWNLENGTH);
// now the first quantity
stci_d(tempstring, worm[player].numbers);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_2ND, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 1));
Text(MainWindowPtr->RPort, tempstring, 4);
// now the second quantity
stci_d(tempstring, BONUS_NUMBER * multiply);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_3RD, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 1));
Text(MainWindowPtr->RPort, tempstring, 4);
Move(MainWindowPtr->RPort, RUNDOWNX, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 2));
Text(MainWindowPtr->RPort, " Time Bonus: #:## x #### =", RUNDOWNLENGTH);
// now the first quantity
tempstring[0] = 48 + (secondsleft / 60);
tempstring[1] = ':';
tempstring[2] = 48 + ((secondsleft % 60) / 10);
tempstring[3] = 48 + ((secondsleft % 60) % 10);
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_2ND, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 2));
Text(MainWindowPtr->RPort, tempstring, 4);
// now the second quantity
stci_d(tempstring, BONUS_TIME * multiply);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_3RD, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 2));
Text(MainWindowPtr->RPort, tempstring, 4);
Move(MainWindowPtr->RPort, RUNDOWNX, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 3));
Text(MainWindowPtr->RPort, " Tail Bonus: ## x #### =", RUNDOWNLENGTH);
// now the first quantity
for (x = 0; x <= FIELDX; x++)
{ for (y = 0; y <= FIELDY; y++)
{ if (field[x][y] == FIRSTTAIL + player || field[x][y] == FIRSTGLOW + player)
{ counter++;
} } }
stci_d(tempstring, counter);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_2ND, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 3));
Text(MainWindowPtr->RPort, tempstring, 4);
// now the second quantity
stci_d(tempstring, BONUS_TAIL * multiply);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_3RD, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 3));
Text(MainWindowPtr->RPort, tempstring, 4);
levelbonus = (level - 1) * BONUS_LEVEL * multiply;
numberbonus = worm[player].numbers * BONUS_NUMBER * multiply;
timebonus = secondsleft * BONUS_TIME * multiply;
tailbonus = counter * BONUS_TAIL * multiply;
for (i = 0; i <= 3; i++)
if (worm[i].control != NONE)
for (j = 0; j <= LASTOBJECT; j++)
stat(i, j);
while (!done)
{ while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP)
done = TRUE;
}
if (done)
{ wormscore
( player,
( levelbonus / multiply) +
(numberbonus / multiply) +
( timebonus / multiply) +
( tailbonus / multiply)
);
levelbonus = timebonus = tailbonus = numberbonus = 0;
}
SetAPen(MainWindowPtr->RPort, worm[player].colour);
stci_d(tempstring, levelbonus);
align(tempstring, 5, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_4TH, RUNDOWNY + RUNDOWNY_2ND );
Text(MainWindowPtr->RPort, tempstring, 5);
stci_d(tempstring, numberbonus);
align(tempstring, 5, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_4TH, RUNDOWNY + RUNDOWNY_2ND + SQUAREY );
Text(MainWindowPtr->RPort, tempstring, 5);
stci_d(tempstring, timebonus);
align(tempstring, 5, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_4TH, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 2));
Text(MainWindowPtr->RPort, tempstring, 5);
stci_d(tempstring, tailbonus);
align(tempstring, 5, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_4TH, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * 3));
Text(MainWindowPtr->RPort, tempstring, 5);
done = TRUE;
if (levelbonus)
{ if (levelbonus >= multiply * 2)
{ levelbonus -= multiply * 2;
wormscore(player, 2);
} else
{ levelbonus -= multiply;
wormscore(player, 1);
}
done = FALSE;
}
if (numberbonus)
{ if (numberbonus >= multiply * 2)
{ numberbonus -= multiply * 2;
wormscore(player, 2);
} else
{ numberbonus -= multiply;
wormscore(player, 1);
}
done = FALSE;
}
if (timebonus)
{ if (timebonus >= multiply * 2)
{ timebonus -= multiply * 2;
wormscore(player, 2);
} else
{ timebonus -= multiply;
wormscore(player, 1);
}
done = FALSE;
}
if (tailbonus)
{ if (tailbonus >= multiply * 2)
{ tailbonus -= multiply * 2;
wormscore(player, 2);
} else
{ tailbonus -= multiply;
wormscore(player, 1);
}
done = FALSE;
}
effect(FXCLICK);
}
clearkybd();
effect(FXRIFF);
for (i = 0; i <= 3; i++)
{ if (worm[i].control == KEYBOARD || worm[i].control == JOYSTICK)
{ flag = TRUE;
break;
} }
if (flag)
{ anykey(FALSE);
} }
void say(STRPTR sentence, COLOUR colour)
{ SWORD length = (SBYTE) strlen(sentence),
centrex;
centrex = STARTXPIXEL + ((ENDXPIXEL - STARTXPIXEL) / 2);
/* truncate text */
if (length > SAYLIMIT)
{ *(sentence + SAYLIMIT) = 0;
length = SAYLIMIT;
}
/* clear areas to left and right of text, respectively */
SetAPen(MainWindowPtr->RPort, BLACK);
RectFill
( MainWindowPtr->RPort,
STARTXPIXEL,
2,
centrex - (length * FONTX / 2),
14
);
RectFill
( MainWindowPtr->RPort,
centrex + (length * FONTX / 2) + 1,
2,
ENDXPIXEL,
14
);
Move(MainWindowPtr->RPort, centrex - (length * FONTX / 2), 2);
Draw(MainWindowPtr->RPort, centrex + (length * FONTX / 2), 2);
/* render shadow text */
SetAPen(MainWindowPtr->RPort, MEDIUMGREY);
Move(MainWindowPtr->RPort, centrex - (length * FONTX / 2) + 1, FONTY + 3);
Text(MainWindowPtr->RPort, sentence, length);
/* render actual text */
SetDrMd(MainWindowPtr->RPort, JAM1);
SetAPen(MainWindowPtr->RPort, colour);
Move(MainWindowPtr->RPort, centrex - (length * FONTX / 2), FONTY + 3);
Text(MainWindowPtr->RPort, sentence, length);
SetDrMd(MainWindowPtr->RPort, JAM2);
}
void stat(SBYTE player, SBYTE line)
{ ABOOL print = TRUE;
SBYTE i, theline;
TEXT output[7];
strcpy(output, " "); /* 7 spaces */
switch (line)
{
case BONUS:
do
{ worm[player].oldscore += (LIFEMODULO - (worm[player].oldscore % LIFEMODULO));
if (worm[player].score >= worm[player].oldscore)
{ worm[player].lives++;
stat(player, LIFE);
} }
while (worm[player].score > worm[player].oldscore);
worm[player].oldscore = worm[player].score;
if (worm[player].multi > 1)
SetAPen(MainWindowPtr->RPort, WHITE);
else SetAPen(MainWindowPtr->RPort, worm[player].colour);
stcl_d(output, worm[player].score);
theline = 0;
for (i = 0; i <= 6; i++)
if (!output[i])
output[i] = ' ';
// score can't reach 10 million
break;
case LIFE:
if (worm[player].lives > STARTLIVES)
{ SetAPen(MainWindowPtr->RPort, WHITE);
if (worm[player].lives > LIVESLIMIT)
worm[player].lives = LIVESLIMIT;
} else SetAPen(MainWindowPtr->RPort, worm[player].colour);
stci_d(output, worm[player].lives);
for (i = 0; i <= 6; i++)
if (!output[i])
output[i] = ' ';
theline = 1;
break;
case BRAKES:
if (worm[player].brakes)
SetAPen(MainWindowPtr->RPort, WHITE);
else SetAPen(MainWindowPtr->RPort, worm[player].colour);
if (worm[player].speed == FAST)
strcpy(output, "Fast ");
elif (worm[player].speed == NORMAL)
strcpy(output, "Normal ");
elif (worm[player].speed == SLOW)
strcpy(output, "Slow ");
else
{ // assert(worm[player].speed == VERYSLOW);
strcpy(output, "V.Slow ");
}
theline = 2;
break;
case AMMO:
if (worm[player].ammo)
{ if (worm[player].ammo > AMMOLIMIT)
worm[player].ammo = AMMOLIMIT;
SetAPen(MainWindowPtr->RPort, WHITE);
} else SetAPen(MainWindowPtr->RPort, worm[player].colour);
stci_d(output, worm[player].ammo);
for (i = 0; i <= 6; i++)
if (!output[i])
output[i] = ' ';
theline = 3;
break;
case POWER:
switch(worm[player].power)
{
case 0:
SetAPen(MainWindowPtr->RPort, worm[player].colour);
strcpy(output, "Single ");
break;
case 2:
SetAPen(MainWindowPtr->RPort, WHITE);
strcpy(output, "Triple ");
break;
case 4:
SetAPen(MainWindowPtr->RPort, WHITE);
strcpy(output, "Quint. ");
break;
case 6:
SetAPen(MainWindowPtr->RPort, WHITE);
strcpy(output, "Sept. ");
break;
default:
break;
}
theline = 4;
break;
case ARMOUR:
if (worm[player].armour > ARMOURLIMIT)
worm[player].armour = ARMOURLIMIT;
if (worm[player].armour > 0)
SetAPen(MainWindowPtr->RPort, WHITE);
else SetAPen(MainWindowPtr->RPort, worm[player].colour);
stci_d(output, worm[player].armour);
for (i = 0; i <= 6; i++)
if (!output[i])
output[i] = ' ';
theline = 5;
break;
case BIAS:
if (worm[player].bias > 0)
{ if (worm[player].bias > BIASLIMIT)
worm[player].bias = BIASLIMIT;
SetAPen(MainWindowPtr->RPort, WHITE);
} else SetAPen(MainWindowPtr->RPort, worm[player].colour);
stci_d(output, worm[player].bias);
for (i = 0; i <= 6; i++)
if (!output[i])
output[i] = ' ';
theline = 6;
break;
default:
print = FALSE;
/* This next line is just to prevent spurious compiler
warnings about possibly uninitialized variables */
theline = 0;
break;
}
/* Sometimes stat() is called with a valid line, yet an invalid player.
Defensive programming currently ensures that this is not a problem, but
it would be better to fix the bug. */
if (print)
{ Move
( MainWindowPtr->RPort,
FONTX * 3,
STARTYPIXEL + (player * SQUAREX * 10) + 8 + (theline * SQUAREY)
);
Text(MainWindowPtr->RPort, output, 7);
} }
void stopfx(void)
{ SBYTE i;
if (mode == FX)
for (i = 0; i <= 3; i++)
// CheckIO() returns NULL if complete, pointer if incomplete? (!)
if (eversent[i] && (!(CheckIO((struct IORequest *) AudioRqPtr[i]))))
{ AbortIO((struct IORequest *) AudioRqPtr[i]);
WaitIO((struct IORequest *) AudioRqPtr[i]);
} }
void titlescreen(void)
{ SBYTE object = LASTOBJECT, player, i;
SWORD descx = FIRSTDESCX;
ULONG class;
UWORD code, qual;
TEXT tempstring[8];
struct IntuiMessage* MsgPtr;
struct Gadget* WhichGadgetPtr;
struct MenuItem* ItemPtr;
effect(FXLAUNCH);
Forbid();
MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
Permit();
clearscreen();
SetMenuStrip(MainWindowPtr, MenuPtr);
for (player = 0; player <= 3; player++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
}
GT_SetGadgetAttrs(RandomGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
GT_SetGadgetAttrs(FEGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
GT_SetGadgetAttrs(PlayGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
SetAPen(MainWindowPtr->RPort, MEDIUMGREY);
SetDrMd(MainWindowPtr->RPort, JAM1);
Move(MainWindowPtr->RPort, 370 + 50 - ((14 + 1) * SQUAREX), TSOFFSET + 170 + 7);
Text(MainWindowPtr->RPort, "Shuffle Levels?", 15);
Move(MainWindowPtr->RPort, 370 + 50 - ((14 + 1) * SQUAREX), TSOFFSET + 170 + 7 + 1);
Text(MainWindowPtr->RPort, "_", 1);
strcpy(tempstring, "Worm :");
for (player = 0; player <= 3; player++)
{ tempstring[5] = '1' + player;
SetAPen(MainWindowPtr->RPort, worm[player].dimcolour);
Move(MainWindowPtr->RPort, 320 - ((7 + 1) * SQUAREX), TSOFFSET + 200 + 9 + (player * 16) );
Text(MainWindowPtr->RPort, tempstring, 7);
Move(MainWindowPtr->RPort, 300 - ((2 + 1) * SQUAREX), TSOFFSET + 200 + 9 + (player * 16) + 1);
Text(MainWindowPtr->RPort, "_", 1);
}
RefreshGList(FEGadgetPtr, MainWindowPtr, NULL, 1);
RefreshGList(PlayGadgetPtr, MainWindowPtr, NULL, 1);
clearkybd();
hiscores();
hiscorenames();
SetDrMd(MainWindowPtr->RPort, JAM2);
DrawImage(MainWindowPtr->RPort, &Logo, 168, 48);
do
{ TimerRqPtr->tr_node.io_Command = TR_ADDREQUEST;
TimerRqPtr->tr_time.tv_secs = 0;
TimerRqPtr->tr_time.tv_micro = ANIMDELAY;
SendIO((struct IORequest *) TimerRqPtr);
if (descx == FIRSTDESCX)
{ if (++object > LASTOBJECT)
{ object = 0;
}
say(objectdesc[object], WHITE);
Image.ImageData = ImageData[object];
DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
}
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, descx - 1, DESCY - 1);
Draw(MainWindowPtr->RPort, descx - 1, DESCY + 1 + SQUAREY);
Move(MainWindowPtr->RPort, descx + 1 + SQUAREX, DESCY - 1);
Draw(MainWindowPtr->RPort, descx + 1 + SQUAREX, DESCY + 1 + SQUAREY);
Image.ImageData = ImageData[object];
DrawImage(MainWindowPtr->RPort, &Image, descx, DESCY);
if (++descx > SECONDDESCX)
{ descx = FIRSTDESCX;
}
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ WhichGadgetPtr = (struct Gadget *) MsgPtr->IAddress;
class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch (class)
{
case IDCMP_RAWKEY:
if (!(qual & IEQUALIFIER_REPEAT))
{ switch (code)
{
case F:
toggle(F);
break;
case M:
toggle(M);
break;
case SPACEBAR:
a = FIELDEDIT;
break;
case F1:
case ALPHAONE:
case NUMERICONE:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (--worm[0].control < 0)
worm[0].control = 4;
} else
{ if (++worm[0].control > 4)
worm[0].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[0], MainWindowPtr, NULL, GTCY_Active, worm[0].control, TAG_DONE);
break;
case F2:
case ALPHATWO:
case NUMERICTWO:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (--worm[1].control < 0)
worm[1].control = 4;
} else
{ if (++worm[1].control > 4)
worm[1].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[1], MainWindowPtr, NULL, GTCY_Active, worm[1].control, TAG_DONE);
break;
case F3:
case ALPHATHREE:
case NUMERICTHREE:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (worm[2].control > 0)
{ worm[2].control--;
} else worm[2].control = 3;
} else
{ if (worm[2].control < 3)
{ worm[2].control++;
} else worm[2].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
break;
case F4:
case ALPHAFOUR:
case NUMERICFOUR:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (--worm[3].control < 0)
worm[3].control = 3;
} else
{ if (++worm[3].control > 3)
worm[3].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[3], MainWindowPtr, NULL, GTCY_Active, worm[3].control, TAG_DONE);
break;
case RETURN:
case ENTER:
a = PLAYGAME;
break;
case S:
randomflag = !randomflag;
GT_SetGadgetAttrs(RandomGadgetPtr, MainWindowPtr, NULL, GTCB_Checked, randomflag, TAG_DONE);
break;
case ESCAPE:
if (verify())
cleanexit(EXIT_SUCCESS);
break;
case HELP:
helpabout();
break;
default:
break;
} }
break;
case IDCMP_MENUPICK:
while (code != MENUNULL)
{ ItemPtr = ItemAddress(MenuPtr, code);
switch (MENUNUM(code))
{
case MN_PROJECT:
switch (ITEMNUM(code))
{
case IN_NEW:
newfields();
say("New done.", WHITE);
anykey(TRUE);
say(objectdesc[object], WHITE);
break;
case IN_OPEN:
fileopen(FALSE);
say(objectdesc[object], WHITE);
break;
case IN_REVERT:
fileopen(TRUE);
say(objectdesc[object], WHITE);
break;
case IN_SAVE:
filesaveas(FALSE);
say(objectdesc[object], WHITE);
break;
case IN_SAVEAS:
filesaveas(TRUE);
say(objectdesc[object], WHITE);
break;
case IN_PROJECTDELETE:
filedelete();
break;
case IN_QUIT:
if (verify())
cleanexit(EXIT_SUCCESS);
break;
default:
break;
}
break;
case MN_SETTINGS:
switch(ITEMNUM(code))
{
case IN_ANIMATIONS:
if (ItemPtr->Flags & CHECKED)
{ anims = TRUE;
} else
{ anims = FALSE;
}
break;
case IN_CREATEICONS:
if (ItemPtr->Flags & CHECKED)
{ icons = TRUE;
} else
{ icons = FALSE;
}
break;
case IN_THICKTAILS:
if (ItemPtr->Flags & CHECKED)
{ thick = TRUE;
} else
{ thick = FALSE;
}
break;
default:
break;
}
break;
case MN_HELP:
switch(ITEMNUM(code))
{
case IN_ABOUT:
helpabout();
break;
case IN_CREATURES:
help(ORB);
break;
case IN_OBJECTS:
help(AFFIXER);
break;
default:
break;
}
break;
default:
break;
}
code = ItemPtr->NextSelect;
}
break;
case IDCMP_MOUSEBUTTONS:
if (code == SELECTDOWN)
{ if (ignore)
{ ignore = FALSE;
} else
{ a = PLAYGAME;
} }
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
break;
case IDCMP_GADGETUP:
if (WhichGadgetPtr == RandomGadgetPtr)
{ randomflag = !randomflag;
} elif (WhichGadgetPtr == PlayGadgetPtr)
{ a = PLAYGAME;
} elif (WhichGadgetPtr == FEGadgetPtr)
{ a = FIELDEDIT;
} else
{ for (player = 0; player <= 3; player++)
{ if (WhichGadgetPtr == CycleGadgetPtr[player])
{ worm[player].control = code;
break;
} } }
break;
case IDCMP_ACTIVEWINDOW:
ignore = TRUE;
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
case IDCMP_INTUITICKS:
for (i = 0; i <= HISCORES; i++)
{ if (anims && hiscore[i].player != -1)
{ Image.ImageData = ImageData[missileframes[hiscore[i].player][hiframe]];
DrawImage(MainWindowPtr->RPort, &Image, 540, TSOFFSET + 3 + (i * HISCOREDISTANCE));
if (++hiframe > MISSILEFRAMES)
{ hiframe = 0;
} } }
break;
default:
; /* IDCMP_MENUVERIFY */
break;
} }
if (firebutton())
{ a = PLAYGAME;
}
if (a == PLAYGAME)
{ if (worm[0].control == NONE && worm[1].control == NONE && worm[2].control == NONE && worm[3].control == NONE)
{ say("No worms active!", WHITE);
anykey(TRUE);
a = GAMEOVER;
} elif
( !LowLevelBase &&
(worm[0].control == GAMEPAD
|| worm[1].control == GAMEPAD
|| worm[2].control == GAMEPAD
|| worm[3].control == GAMEPAD
) )
{ say("Need OS3.1+ for gamepad!", WHITE);
anykey(TRUE);
a = GAMEOVER;
} }
// CheckIO() returns NULL if complete, pointer if incomplete.
if (CheckIO((struct IORequest *) TimerRqPtr))
draw(CLOCKICON, ICONY, CLOCK);
else draw(CLOCKICON, ICONY, BLACKENED);
WaitIO((struct IORequest *) TimerRqPtr);
} while (a == GAMEOVER);
for (player = 0; player <= 3; player++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
}
GT_SetGadgetAttrs(RandomGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
GT_SetGadgetAttrs(FEGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
GT_SetGadgetAttrs(PlayGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
Image.ImageData = ImageData[BLACKENED];
DrawImage(MainWindowPtr->RPort, &Image, FIRSTDESCX, DESCY);
DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
if (a == FIELDEDIT)
{ fieldedit();
} else
{ turbo = FALSE;
newgame();
clearkybd();
Forbid();
MainWindowPtr->Flags |= WFLG_RMBTRAP;
Permit();
} }
AGLOBAL void toggle(SBYTE key)
{ PERSIST ABOOL songstarted = FALSE;
switch(key)
{
case F:
if (mode == FX) /* F in FX mode: no sound */
{ freefx();
mode = FALSE;
draw(MUSICICON, ICONY, BLACKENED);
} else if (fxable != FAILED) /* F otherwise: change to FX mode */
{ if (mode == MUSIC) /* stop any music that is playing */
{ StopPlayer();
FreePlayer();
}
if (fxable == DEFER) /* load samples if needed */
loadthefx();
if (fxable == SUCCEEDED) /* if we have samples in memory */
{ if (beginfx())
{ mode = FX;
effect(FXLAUNCH);
draw(MUSICICON, ICONY, FX);
} } }
break;
case M:
if (mode == MUSIC) /* M in MUSIC mode: no sound */
{ StopPlayer();
FreePlayer();
mode = FALSE;
draw(MUSICICON, ICONY, BLACKENED);
} else if (musicable != FAILED) /* M otherwise: change to music mode */
{ if (mode == FX) /* stop any samples that are playing */
freefx();
/* Of course, these statements are ordered in this
way for a reason, so don't change it. :-) */
if (musicable == DEFER)
loadthemusic();
if (musicable == SUCCEEDED)
{ if (GetPlayer(0))
{ say("No channels for music!", RED);
anykey(TRUE);
mode = FALSE;
draw(MUSICICON, ICONY, BLACKENED);
} else
{ if (songstarted)
ContModule(SongPtr);
else
{ PlayModule(SongPtr);
songstarted = TRUE;
}
mode = MUSIC;
draw(MUSICICON, ICONY, MUSIC);
} } }
break;
default:
flash(2);
// assert(0);
break;
} }
ABOOL verify(void)
{ pausetimer();
if (modified && (EasyRequest(MainWindowPtr, &EasyStruct, NULL) == 0))
return FALSE;
else return TRUE;
unpausetimer();
}
void waitasec(void)
{ Delay(50);
}
void systemsetup(void)
{ worm[0].control = NONE;
worm[1].control = KEYBOARD;
worm[2].control = NONE;
worm[3].control = AMIGA;
}
ABOOL ZOpen(STRPTR fieldname, ABOOL write)
{ if (!write)
if (FilePtr = Open(fieldname, MODE_OLDFILE))
return TRUE;
else return FALSE;
else
if (FilePtr = Open(fieldname, MODE_NEWFILE))
return TRUE;
else return FALSE;
}
ABOOL ZRead(STRPTR IOBuffer, ULONG length)
{ if (Read(FilePtr, IOBuffer, length) == length)
return TRUE;
else return FALSE;
}
ABOOL ZWrite(STRPTR IOBuffer, ULONG length)
{ if (Write(FilePtr, IOBuffer, length) == length)
return TRUE;
else return FALSE;
}
ABOOL ZClose(void)
{ if (Close(FilePtr))
{ FilePtr = NULL;
return TRUE;
} else
{ /* "If Close() returns DOSFALSE, the user has already cancelled an
error requester and the function has already freed the FileHandle
(and even marked it so any attempt to close it again will bring up
the "Software Failure" requester). Therefore FilePtr should be set
to zero in any case." - Jilles Tjoelker. */
FilePtr = NULL;
return FALSE;
} }
void timing(void)
{ ;
}
MODULE void loadthefx(void)
{ UBYTE* p8data;
TEXT saystring[SAYLIMIT + 1];
SBYTE code = 0, i,
iobuffer[8]; /* buffer for 8SVX.VHDR */
SBYTE* psample[2]; /* sample pointers */
struct Chunk* p8Chunk; /* pointers for 8SVX parsing */
Voice8Header* pVoice8Header = NULL; // only set to NULL to avoid spurious warnings
ULONG rd8count;
say("Loading sound effects...", WHITE);
fxable = SUCCEEDED;
for (i = 0; i <= SAMPLES; i++)
samp[i].base = NULL;
for (i = 0; i <= SAMPLES; i++)
{ if (!(FilePtr = Open(samp[i].filename, MODE_OLDFILE)))
code = 1; /* can't open file */
else
{ rd8count = Read(FilePtr, iobuffer, 8L);
if (rd8count == -1)
code = 2; /* can't read file */
elif (rd8count < 8)
code = 3; /* not an IFF 8SVX; too short */
else
{ p8Chunk = (struct Chunk *) iobuffer;
if (p8Chunk->ckID != ID_FORM)
code = 4; /* not an IFF FORM */
elif (!(fbase = (UBYTE *) AllocMem(fsize = p8Chunk->ckSize, MEMF_PUBLIC | MEMF_CLEAR)))
code = 5; /* no memory for read */
else
{ p8data = fbase;
rd8count = Read(FilePtr, p8data, p8Chunk->ckSize);
if (rd8count == -1)
code = 6; /* read error */
elif (rd8count < p8Chunk->ckSize)
code = 7; /* malformed IFF; too short */
elif (MAKE_ID(*p8data, *(p8data + 1), *(p8data + 2), *(p8data + 3)) != ID_8SVX)
code = 8; /* not an IFF 8SVX */
else
{ p8data = p8data + 4;
while (p8data < fbase + fsize)
{ p8Chunk = (struct Chunk *) p8data;
switch(p8Chunk->ckID)
{
case ID_VHDR:
pVoice8Header = (Voice8Header *) (p8data + 8L);
break;
case ID_BODY:
psample[0] = (SBYTE *) (p8data + 8L);
psample[1] = psample[0] + pVoice8Header->oneShotHiSamples;
samp[i].length[0] = (ULONG) pVoice8Header->oneShotHiSamples;
samp[i].length[1] = (ULONG) pVoice8Header->repeatHiSamples;
/* To grab the volume level from the IFF
8SVX file itself, add this line here:
samp[i].volume = (SBYTE) (pVoice8Header->volume / 156); */
break;
default:
break;
}
p8data += 8L + p8Chunk->ckSize;
if (p8Chunk->ckSize & 1L == 1)
p8data++;
}
if (samp[i].length[0] == 0)
samp[i].bank = 1;
else samp[i].bank = 0;
if (samp[i].length[samp[i].bank] <= 102400)
samp[i].size = samp[i].length[samp[i].bank];
else samp[i].size = 102400;
samp[i].base = (UBYTE *) AllocMem(samp[i].size, MEMF_CHIP | MEMF_CLEAR);
if (!samp[i].base)
code = 9; /* no chip memory */
else
{ CopyMem(psample[samp[i].bank], samp[i].base, samp[i].size);
psample[samp[i].bank] += samp[i].size;
if (GfxBase->DisplayFlags & PAL) // PAL clock
{ samp[i].speed = PALCLOCK / pVoice8Header->samplesPerSec;
} else // NTSC clock
{ samp[i].speed = NTSCCLOCK / pVoice8Header->samplesPerSec;
}
/* "The maximum frequency achievable depends on the screen rate because
the Paula audio DMA period depends on the horizontal refresh rate, but the
actual clock rate of Paula by which the audio DA converters are driven
depends really only on the clock rate.
It's fixed for either PAL or NTSC machines, NOT for PAL or NTSC screen
modes. Hence just the two values that are given in the RKRMs are
completely sufficient. Note that running an NTSC screen on a PAL machine
does not change the system clock and hence neither the audio frequency.
It changes horizontal timing and vertical timing, and hence the minimal
audio period." - Thomas `Thor' Richter. */
if (fbase)
{ FreeMem(fbase, fsize);
fbase = NULL;
}
if (FilePtr)
{ Close(FilePtr);
FilePtr = NULL;
} } } } } }
if (code)
{ freefx();
fxable = FAILED;
strcpy(saystring, samp[i].filename);
strcat(saystring, ": ");
strcat(saystring, sfxerror[code]);
say(saystring, RED);
anykey(TRUE);
break;
} } }
MODULE void loadthemusic(void)
{ if (!(MEDPlayerBase = (struct MEDPlayerBase *) OpenLibrary("medplayer.library", 0L)))
{ say("Can't open MEDPlayer.library!", RED);
anykey(TRUE);
} else
{ say("Loading music...", WHITE);
if (SongPtr = (struct MMD0 *) LoadModule("PROGDIR:WormWars.MED"))
musicable = SUCCEEDED;
else
{ say("Can't load music!", RED);
anykey(TRUE);
} } }
void clearscreen(void)
{ SBYTE i;
SetAPen(MainWindowPtr->RPort, BLACK);
RectFill(MainWindowPtr->RPort, 0, 0, ENTIREXPIXEL, ENTIREYPIXEL);
if (mode == MUSIC)
draw(MUSICICON, ICONY, MUSIC);
elif (mode == FX)
draw(MUSICICON, ICONY, FX);
else draw(MUSICICON, ICONY, BLACKENED);
draw(CLOCKICON, ICONY, CLOCK);
if (a != FIELDEDIT)
{ for (i = 0; i <= 3; i++)
{ if (worm[i].control != NONE)
{ draw(-6, (i * 10) , BONUS);
draw(-6, (i * 10) + 1, LIFE);
draw(-6, (i * 10) + 2, BRAKES);
draw(-6, (i * 10) + 3, AMMO);
draw(-6, (i * 10) + 4, POWER);
draw(-6, (i * 10) + 5, ARMOUR);
draw(-6, (i * 10) + 6, BIAS);
} }
for (i = 0; i <= 3; i++)
{ icon(i, REMNANTS);
icon(i, AFFIXER);
icon(i, SIDESHOT);
icon(i, PUSHER);
icon(i, GLOW);
icon(i, CUTTER);
icon(i, ENCLOSER);
} } }
void datestamp(void)
{ ULONG seconds, micros;
struct ClockData Date;
TEXT temp[5];
CurrentTime(&seconds, µs);
Amiga2Date(seconds, &Date);
stci_d(times, Date.hour); /* hh */
align(times, 2, ' ');
times[2] = ':'; /* hh: */
times[3] = 0;
stci_d(temp, Date.min);
align(temp, 2, '0');
temp[2] = 0;
strcat(times, temp); /* hh:mm */
stci_d(date, Date.mday); /* dd */
align(date, 2, ' ');
date[2] = '/';
date[3] = 0; /* dd/ */
stci_d(temp, Date.month);
align(temp, 2, ' ');
temp[2] = 0;
strcat(date, temp); /* dd/mm */
strcat(date, "/"); /* dd/mm/ */
stci_d(temp, Date.year);
temp[0] = temp[2];
temp[1] = temp[3];
temp[2] = 0;
strcat(date, temp); /* dd/mm/yy */
}
void turborender(void)
{ UBYTE random = rand() % 2;
SBYTE x, y;
if (a != PLAYGAME || (!level) || !(randomflag))
sourcelevel = level;
switch(random)
{
case 0:
for (x = 0; x <= CENTREX + 1; x++)
for (y = 0; y <= FIELDY / 2; y++)
{ draw(x, y, board[sourcelevel][x][y]);
draw(FIELDX - x, y, board[sourcelevel][FIELDX - x][y]);
draw(x, FIELDY - y, board[sourcelevel][x][FIELDY - y]);
draw(FIELDX - x, FIELDY - y, board[sourcelevel][FIELDX - x][FIELDY - y]);
}
break;
case 1:
for (y = 0; y <= FIELDY / 2; y++)
for (x = 0; x <= CENTREX + 1; x++)
{ draw(x, y, board[sourcelevel][x][y]);
draw(FIELDX - x, y, board[sourcelevel][FIELDX - x][y]);
draw(x, FIELDY - y, board[sourcelevel][x][FIELDY - y]);
draw(FIELDX - x, FIELDY - y, board[sourcelevel][FIELDX - x][FIELDY - y]);
}
break;
default:
assert(0);
break;
}
if (a == FIELDEDIT)
{ draw(startx[sourcelevel], starty[sourcelevel], START);
} else
{ for (y = 0; y <= FIELDY; y++)
{ draw(ARROWX, y, BLACKENED);
} }
SetAPen(MainWindowPtr->RPort, MEDIUMGREY);
Move(MainWindowPtr->RPort, STARTXPIXEL , ENDYPIXEL + 1);
Draw(MainWindowPtr->RPort, ENDXPIXEL , ENDYPIXEL + 1);
Move(MainWindowPtr->RPort, ENDXPIXEL + 1, STARTYPIXEL );
Draw(MainWindowPtr->RPort, ENDXPIXEL + 1, ENDYPIXEL + 1);
}
MODULE void parsewb(void)
{ struct DiskObject* DiskObject;
char** ToolArray;
char* s;
if ((*WBArg->wa_Name) && (DiskObject = GetDiskObject(WBArg->wa_Name)))
{ ToolArray = (char **) DiskObject->do_ToolTypes;
if (s = (char *) FindToolType(ToolArray, "NOPRELOAD"))
{ fxable = musicable = DEFER;
}
if (s = (char *) FindToolType(ToolArray, "NOANIMS"))
{ anims = FALSE;
}
if (s = (char *) FindToolType(ToolArray, "NOICONS"))
{ icons = FALSE;
}
if (s = (char *) FindToolType(ToolArray, "SHUFFLE"))
{ randomflag = TRUE;
}
if (s = (STRPTR) FindToolType(ToolArray, "QUIET"))
{ quiet = TRUE;
}
if (s = (char *) FindToolType(ToolArray, "THICKTAILS"))
{ thick = TRUE;
}
if (s = (char *) FindToolType(ToolArray, "FILE"))
{ strcpy(pathname, WBArg->wa_Name);
}
if (s = (char *) FindToolType(ToolArray, "GREEN"))
{ if (MatchToolValue(s, "KYBD"))
{ worm[0].control = KEYBOARD;
} elif (MatchToolValue(s, "JOY"))
{ worm[0].control = JOYSTICK;
} elif (MatchToolValue(s, "GAMEPAD"))
{ worm[0].control = GAMEPAD;
} elif (MatchToolValue(s, "AMIGA"))
{ worm[0].control = AMIGA;
} elif (MatchToolValue(s, "NONE"))
{ worm[0].control = NONE;
} }
if (s = (char *) FindToolType(ToolArray, "RED"))
{ if (MatchToolValue(s, "KYBD"))
{ worm[1].control = KEYBOARD;
} elif (MatchToolValue(s, "JOY"))
{ worm[1].control = JOYSTICK;
} elif (MatchToolValue(s, "GAMEPAD"))
{ worm[1].control = GAMEPAD;
} elif (MatchToolValue(s, "AMIGA"))
{ worm[1].control = AMIGA;
} elif (MatchToolValue(s, "NONE"))
{ worm[1].control = NONE;
} }
if (s = (char *) FindToolType(ToolArray, "BLUE"))
{ if (MatchToolValue(s, "JOY"))
{ worm[2].control = JOYSTICK;
} elif (MatchToolValue(s, "GAMEPAD"))
{ worm[2].control = GAMEPAD;
} elif (MatchToolValue(s, "AMIGA"))
{ worm[2].control = AMIGA;
} elif (MatchToolValue(s, "NONE"))
{ worm[2].control = NONE;
} }
if (s = (char *) FindToolType(ToolArray, "YELLOW"))
{ if (MatchToolValue(s, "JOY"))
{ worm[3].control = JOYSTICK;
} elif (MatchToolValue(s, "GAMEPAD"))
{ worm[3].control = GAMEPAD;
} elif (MatchToolValue(s, "AMIGA"))
{ worm[3].control = AMIGA;
} elif (MatchToolValue(s, "NONE"))
{ worm[3].control = NONE;
} }
FreeDiskObject(DiskObject);
} }
MODULE void pausetimer(void)
{ GetSysTime(CurrentValPtr);
}
MODULE void unpausetimer(void)
{ GetSysTime(PausedValPtr);
SubTime(PausedValPtr, CurrentValPtr);
AddTime(StartValPtr, PausedValPtr);
}
MODULE UBYTE ReadJoystick(UWORD joynum)
{ extern struct Custom far custom;
UBYTE ret = 0;
UWORD joy;
if (joynum == 0)
joy = custom.joy0dat;
else joy = custom.joy1dat;
ret += (joy >> 1 ^ joy) & 0x0100 ? JOYUP : 0;
ret += (joy >> 1 ^ joy) & 0x0001 ? JOYDOWN : 0;
ret += joy & 0x0200 ? JOYLEFT : 0;
ret += joy & 0x0002 ? JOYRIGHT : 0;
if (joynum == 0)
{ ret += !(CIAPtr->ciapra & 0x0040) ? JOYFIRE1 : 0; /* read firebuttons */
ret += !(POTGOR & 0x0400) ? JOYFIRE2 : 0; /* on joyport 0 */
} else
{ ret += !(CIAPtr->ciapra & 0x0080) ? JOYFIRE1 : 0; /* read firebuttons */
ret += !(POTGOR & 0x0400) ? JOYFIRE2 : 0; /* on joyport 1 */
}
return(ret);
}
AGLOBAL void ReadAdapterJoystick(UBYTE unit)
{ AUTO UBYTE firebit, addroffset, snapshot;
AUTO SBYTE xx = 0, yy = 0;
AUTO ABOOL fire = FALSE;
PERSIST UBYTE oldsnapshot[2] = {0, 0};
PERSIST ABOOL oldfire[2] = {0, 0};
PERSIST UBYTE *fireaddrPtr,
*moveaddrPtr;
fireaddrPtr = 0xBFD000;
moveaddrPtr = 0xBFE101;
/* Those pointers could easily be auto or constant or whatever; they
never change.
bit 7 of $bfe101 is right of joystick '4'
bit 6 of $bfe101 is left of joystick '4'
bit 5 of $bfe101 is down of joystick '4'
bit 4 of $bfe101 is up of joystick '4'
bit 3 of $bfe101 is right of joystick '3'
bit 2 of $bfe101 is left of joystick '3'
bit 1 of $bfe101 is down of joystick '3'
bit 0 of $bfe101 is up of joystick '3'
bit 2 of $bfd000 is fire of joystick '3'
bit 0 of $bfd000 is fire of joystick '4'
unit: number of the unit (2 = '3', 3 = '4') */
if (unit == 2)
{ firebit = 2;
addroffset = 0;
} else
{ // assert(unit == 3);
firebit = 0;
addroffset = 4;
}
if (worm[unit].control == JOYSTICK && worm[unit].lives)
{ if ((*fireaddrPtr) & (1 << firebit))
fire = TRUE;
snapshot = *moveaddrPtr; // we cache this address in the snapshot
// variable, so that joystick reading is an
// atomic operation
if (snapshot & (1 << (addroffset + 3)))
xx = 1;
elif (snapshot & (1 << (addroffset + 2)))
xx = -1;
if (snapshot & (1 << (addroffset + 1)))
yy = 1;
elif (snapshot & (1 << addroffset ))
yy = -1;
if (oldsnapshot[unit - 2] != snapshot || oldfire[unit - 2] != fire)
{ if (fire)
wormqueue(unit, 0, 0);
else
wormqueue(unit, xx, yy);
}
oldsnapshot[unit - 2] = snapshot;
oldfire[unit - 2] = fire;
} }
MODULE ABOOL firebutton(void)
{ UBYTE PortState = ReadJoystick(1);
if (PortState & JOYFIRE1) // don't check JOYFIRE2
{ return(TRUE);
} else return(FALSE);
}
AGLOBAL void ReadStandardJoystick(ULONG port)
{ AUTO UBYTE PortState[2];
AUTO ABOOL fire = FALSE;
AUTO SBYTE xx = 0,
yy = 0,
player;
PERSIST UBYTE OldPortState[2] = {0, 0};
if (port == 1)
{ player = 2; // blue worm
} else
{ // assert(port == 0);
player = 3; // yellow worm
}
if (worm[player].control == JOYSTICK && worm[player].lives)
{ PortState[port] = ReadJoystick(port);
if (PortState[port] != OldPortState[port])
{ if (PortState[port] & JOYUP)
yy = -1;
elif (PortState[port] & JOYDOWN)
yy = 1;
if (PortState[port] & JOYLEFT)
xx = -1;
elif (PortState[port] & JOYRIGHT)
xx = 1;
if (PortState[port] & JOYFIRE1)
{ fire = TRUE;
}
// this doesn't work perfectly?
if (PortState[port] != 0 && (worm[player].brakes || xx == 0 || yy == 0))
// if joystick is off-centre or firebutton is down
{ if (fire) // if firebutton is down
{ wormqueue(player, 0, 0); // then shoot/jump
} else // if firebutton is up
{ wormqueue(player, xx, yy); // then move
} } }
OldPortState[port] = PortState[port];
} }
void flash(ULONG where)
{ TEXT saystring[SAYLIMIT + 1];
stci_d(saystring, where);
say(saystring, PURPLE);
while(1);
}
AGLOBAL void ReadGamepads(void)
{ AUTO ULONG PortState;
AUTO ABOOL fire = FALSE;
AUTO SBYTE i, xx = 0, yy = 0;
PERSIST ULONG OldPortState = 0;
for (i = 0; i <= 3; i++)
{ if (worm[i].control == GAMEPAD && worm[i].lives)
{ PortState = ReadJoyPort(worm[i].port);
if (PortState != OldPortState)
{ if (PortState & JP_BUTTON_MASK)
{ fire = TRUE;
}
if (PortState & JPF_JOY_UP)
{ yy = -1;
} elif (PortState & JPF_JOY_DOWN)
{ yy = 1;
}
if (PortState & JPF_JOY_LEFT)
{ xx = -1;
} elif (PortState & JPF_JOY_RIGHT)
{ xx = 1;
}
if (fire) // if firebutton is down
{ wormqueue(i, 0, 0); // then shoot/jump
} elif (xx || yy)
{ wormqueue(i, xx, yy);
} }
OldPortState = PortState;
} } }